# Migrating from Kiosk SDK V1

The original version of Kiosk SDK provided basic experimentation with the Kiosk API. The new version
of the SDK (0.7+) provides a more robust experience for building kiosk/transfer policy transactions.

The new SDK offers a builder-pattern API, which provides better autocomplete capabilities, and also
makes code more readable.

While a one-to-one mapping between the old and new SDK is not possible, the following examples
should help you get started.

> An important benefit of the new SDK is that it works seamlessly with Personal Kiosk, which was not
> the case with the previous SDK (you would always have to wrap the transaction with `borrow_cap` /
> `return_cap` calls depending on whether the kiosk is personal or not).

## Placing an item to kiosk and listing it for sale

The following example is from the original Kiosk SDK V1 documentation.

### Before

```typescript
import { placeAndList } from '@mysten/kiosk';
import { Transaction } from '@mysten/sui/transactions';

const placeAndListToKiosk = async () => {
	const kiosk = 'SomeKioskId';
	const kioskCap = 'KioskCapObjectId';
	const itemType = '0xItemAddr::some:ItemType';
	const item = 'SomeItemId';
	const price = '100000';

	const tx = new Transaction();

	placeAndList(tx, itemType, kiosk, kioskCap, item, price);

	// ... continue to sign and execute the transaction
	// ...
};
```

### After

Using the new SDK, you can build the same transaction as follows:

```typescript
/// You need to do this only once and re-use it in the application.
const kioskClient = new KioskClient({
	client: new SuiClient({
		url: getFullnodeUrl('mainnet'),
	}),
	network: Network.MAINNET,
});

const placeAndListToKiosk = async () => {
	// Assume you have saved the user's preferred kiosk Cap somewhere in your app's state.
	const { kioskOwnerCaps } = await kioskClient.getOwnedKiosks({ address: '0xSomeAddress' });

	const tx = new Transaction();

	// Assume you use the first owned kiosk.
	new KioskTransaction({ transaction: tx, kioskClient, cap: kioskOwnerCaps[0] })
		.placeAndList({
			itemType: '0xItemAddr::some:ItemType',
			item: 'SomeItemId',
			price: '100000',
		})
		.finalize();

	// ... continue to sign and execute the transaction
};
```

## Create a new kiosk

The following example is from the original Kiosk SDK V1 documentation.

### Before

```typescript
import { createKioskAndShare } from '@mysten/kiosk';
import { Transaction } from '@mysten/sui/transactions';

const createKiosk = async () => {
	const accountAddress = '0xSomeSuiAddress';

	const tx = new Transaction();
	const kiosk_cap = createKioskAndShare(tx);

	tx.transferObjects([kiosk_cap], accountAddress);

	// ... continue to sign and execute the transaction
	// ...
};
```

### After

Using the new SDK, you can build the same transaction as follows:

```typescript
/// You need to do this only once and re-use it in the application.
const kioskClient = new KioskClient({
	client: new SuiClient({
		url: getFullnodeUrl('mainnet'),
	}),
	network: Network.MAINNET,
});

const placeAndListToKiosk = async () => {
	const tx = new Transaction();

	const kioskTx = new KioskTransaction({ transaction: tx, kioskClient });

	kioskTx.shareAndTransferCap('0xSomeSuiAddress').finalize();

	// ... continue to sign and execute the transaction
};
```

## Purchasing an item and resolving rules

The following example is from the original Kiosk SDK V1 documentation.

### Before

```typescript
import { queryTransferPolicy, purchaseAndResolvePolicies, place, testnetEnvironment } from '@mysten/kiosk';
import { SuiClient } from '@mysten/sui/client';

const client = new SuiClient(
  url: 'https://fullnode.testnet.sui.io:443',
);

// The kiosk we're purchasing from.
const kioskId = `0xSomeKioskAddress`;
// A sample item retrieved from `fetchKiosk` function (or hard-coded).
const item = {
  isLocked: false,
  objectId: "0xb892d61a9992a10c9453efcdbd14ca9720d7dc1000a2048224209c9e544ed223"
  type: "0x52852c4ba80040395b259c641e70b702426a58990ff73cecf5afd31954429090::test::TestItem",
  listing: {
    isExclusive: false,
    listingId: "0x368b512ff2514dbea814f26ec9a3d41198c00e8ed778099961e9ed22a9f0032b",
    price: "20000000000" // in MIST
  }
}
const ownedKiosk = `0xMyKioskAddress`;
const ownedKioskCap = `0xMyKioskOwnerCap`;

const purchaseItem = async (item, kioskId) => {

  // Fetch the policy of the item (could be an array, if there's more than one transfer policy)
  const policies = await queryTransferPolicy(client, item.type);
  // Selecting the first one for simplicity.
  const policyId = policy[0]?.id;
  // Initialize transaction.
  const tx = new Transaction();

  // Both are required if there is a `kiosk_lock_rule`.
  // Optional otherwise. Function throws an error if there's a kiosk_lock_rule and these are missing.
  const extraParams = {
    ownedKiosk,
    ownedKioskCap
  }
  // Define the environment.
  // To use a custom package address for rules, you could call:
  // const environment = customEnvironment('<PackageAddress>');
  const environment = testnetEnvironment;

  // Extra params. Optional, but required if the user tries to resolve a `kiosk_lock_rule`.
  // Purchases the item. Supports `kiosk_lock_rule`, `royalty_rule` (accepts combination too).
  const result = purchaseAndResolvePolicies(tx, item.type, item.listing.price, kioskId, item.objectId, policy[0], environment, extraParams);

  // result = {item: <the_purchased_item>, canTransfer: true/false // depending on whether there was a kiosk lock rule }
  // If the item didn't have a kiosk_lock_rule, you need to do something with it.
  // For example, place it in your own kiosk. (demonstrated below)
  if(result.canTransfer) place(tx, item.type, ownedKiosk, ownedKioskCap , result.item);

  // ...finally, sign PTB & execute it.

};
```

### After

Using the new SDK, you can build the same transaction as follows:

> This works with both personal and non-personal kiosks.

```typescript
/// You need to do this only once and re-use it in the application.
const kioskClient = new KioskClient({
    client: new SuiClient({
        url: getFullnodeUrl('mainnet'),
    }),
    network: Network.MAINNET,
});

// An Item as returned from `kioskClient.getKiosk()` call.
const item = {
  isLocked: false,
  objectId: "0xb892d61a9992a10c9453efcdbd14ca9720d7dc1000a2048224209c9e544ed223"
  type: "0x52852c4ba80040395b259c641e70b702426a58990ff73cecf5afd31954429090::test::TestItem",
  kioskId: '0xSomeKioskAddress',
  listing: {
    isExclusive: false,
    listingId: "0x368b512ff2514dbea814f26ec9a3d41198c00e8ed778099961e9ed22a9f0032b",
    price: "20000000000" // in MIST
  }
}

const purchase = async () => {
    // Assume you have saved the user's preferred kiosk Cap somewhere in your app's state.
    // You wouldn't need to query this for every purchase.
    const { kioskOwnerCaps } = await kioskClient.getOwnedKiosks({ address: '0xSomeAddress' });

    const tx = new Transaction();

    const kioskTx = new KioskTransaction({ transaction: tx, kioskClient, cap: kioskOwnerCaps[0] });

    // Purchase the item and resolve the rules.
    await kioskTx.purchaseAndResolve({
        itemType: item.type,
        itemId: item.objectId,
        price: item.listing.price,
        sellerKiosk: item.kioskId,
    });

    kioskTx.finalize();
};
```

## Attach rules to transfer policy

The following example was taken from the original Kiosk SDK V1 documentation.

### Before

```typescript
import {
	attachKioskLockRule,
	attachRoyaltyRule,
	createTransferPolicy,
	percentageToBasisPoints,
	testnetEnvironment,
} from '@mysten/kiosk';
import { Transaction } from '@mysten/sui/transactions';

// Attaches a royalty rule of 1% or 0.1 SUI (whichever is bigger)
// as well as a kiosk lock, making the objects tradeable only from/to a kiosk.
const attachStrongRoyalties = async () => {
	const type = 'SomePackageId::type::MyType'; // the Type for which we're attaching rules.
	const policyId = 'policyObjectId'; // the transfer Policy ID that was created for that Type.
	const transferPolicyCap = 'transferPolicyCapId'; // the transferPolicyCap for that policy.

	// Royalties configuration.
	const percentage = 2.55; // 2.55%
	const minAmount = 100_000_000; // 0.1 SUI.

	// The environment on which we're referencing the rules package.
	// Use `mainnetEnvironment` for mainnet.
	const environment = testnetEnvironment;

	const tx = new Transaction();

	attachKioskLockRule(tx, type, policyId, policyCapId, environment);
	attachRoyaltyRule(
		tx,
		type,
		policyId,
		policyCapId,
		percentageToBasisPoints(percentage),
		minAmount,
		environment,
	);

	// ... continue to sign and execute the transaction
	// ...
};
```

### After

On the new SDK, the same transaction can be built as follows:

```typescript
/// You need to do this only once and re-use it in the application.
const kioskClient = new KioskClient({
	client: new SuiClient({
		url: getFullnodeUrl('mainnet'),
	}),
	network: Network.MAINNET,
});

const adjustPolicy = async () => {
	const tx = new Transaction();

	// You could have more than one cap, since you can create more than one transfer policy.
	const policyCaps = await kioskClient.getOwnedTransferPoliciesByType({
		type: `SomePackageId::type::MyType`,
		address: '0xOwnerAddress',
	});

	new TransferPolicyTransaction({ transaction: tx, kioskClient, cap: policyCaps[0] })
		.addRoyaltyRule(percentageToBasisPoints(2.55), 100_000_000)
		.addLockRule();

	// ... continue to sign and execute the transaction
	// ...
};
```
